public class newStudentController {
  
    
       // These four member variables maintain the state of the wizard.
       // When users enter data into the wizard, their input is stored
       // in these variables. 
    
       Contact contact;
       Contact contact2;
       Contact guardian2;
       Contact_Connector__c connector;
       Contact_Connector__c studentGuardianConnector2;
       ONEN_Household__c household;
       Student_Enrollment__c enrollment;
       Medical_Form__c medform;
    
        boolean secondGuardian = false;
        boolean printed = false;
        
       // The next methods return one of each of the member
       // variables. If this is the first time the method is called,
       // it creates an empty record for the variable.
       public ONEN_Household__c getHousehold() {
          if(household == null) household = new ONEN_Household__c();
          return household;
       }
    
     
       public Contact getcontact() {
          if(contact == null) contact = new Contact();
          contact.MailingState   = 'CA';
          return contact;
       }
       
       public List<SelectOption> states {
        get {
             Set<String> uniqueStates = new Set<String>();
             List<String> uniqueStateList = new List<String>();
             List<SelectOption> options = new List<SelectOption>(); 
             List<USStates__c> states = USStates__c.getAll().values();
             for (USStates__c s:states) {
                uniqueStates.add(s.state_code__c);
             }
             uniqueStateList.addAll(uniqueStates);
             uniqueStateList.sort();
             for (String uniqueState:uniqueStateList) {
                    options.add(new SelectOption(uniqueState,uniqueState));
             }
             return options;               
        } 
       }
       
       public Contact getContact2() {
          if(contact2 == null) {
                contact2 = new Contact();
          }
          return contact2;
       }
       public Contact getGuardian2() {
          if(guardian2 == null) {
                guardian2 = new Contact();
          }
          return guardian2;
       }
       
       public Contact_Connector__c getConnector() {
          if(connector == null) {
                connector = new Contact_Connector__c();   
          }
          return connector;
       }

       public Contact_Connector__c getStudentGuardianConnector2() {
          if(studentGuardianConnector2 == null) {
                 studentGuardianConnector2 = new Contact_Connector__c();   
          }
          return studentGuardianConnector2;
       }
    
       public  Student_Enrollment__c getEnrollment() {
          if(enrollment == null) { 
            enrollment = new  Student_Enrollment__c();
            //this code doesn't take into account Spring registrations made at the end of the year before.
           // enrollment.Year__c = String.valueOf(date.today().year());
           enrollment.Year__c = '2012';
           
            
          }
          return enrollment;
       }
    
       public  Medical_Form__c getMedform() {
          if(medform == null) medform = new  Medical_Form__c();
          return medform;
       }
    
    
       // The next three methods control navigation through
       // the wizard. Each returns a PageReference for one of the three pages
       // in the wizard. Note that the redirect attribute does not need to
       // be set on the PageReference because the URL does not need to change
       // when users move from page to page.
        public PageReference step1() {
            return Page.StudentDataEntry;
        }

        public PageReference step2() {
            try{   
                //verifies email first, so partial registrations aren't saved.
                verifiesEmails();    
                                    
            } catch(Exception ex){
                ApexPages.addMessages(ex);
                return null;
            } 
                          
            printed = false;
            return Page.StudentDataEntry2;
        }

        public PageReference step3() {   
                     
            contact.FirstName = DataQualityUtilities.capitalizeFirstLetter(contact.FirstName); 
            contact.LastName = DataQualityUtilities.capitalizeFirstLetter(contact.LastName);    
            enrollment.Name = contact.FirstName + ' ' + contact.LastName + ' ' + 
                enrollment.Season__c.substring(0,1).toUpperCase() + enrollment.Year__c.substring(2,4);
                           
            fillHouseholdFields();
            
            return Page.StudentDataEntry3;
        }

        public PageReference stepPrint() {
            printed = true;
            return ApexPages.currentPage();
        }
        
        public PageReference getPdf() {
            PageReference pdf = Page.RegistrationConfirmationPrint;
            if(ApexPages.currentPage().getParameters().get('lang')!=null)
                pdf.getParameters().put('lang',ApexPages.currentPage().getParameters().get('lang'));

            return pdf; 
        } 
            
        public PageReference addGuardian() {
            secondGuardian = true; 
            return ApexPages.currentPage();
        }

        public PageReference removeGuardian() {
            secondGuardian = false; 
            return ApexPages.currentPage();
        }
    
        public boolean getHasSecondGuardian() {
            return secondGuardian;
        }
        
        public boolean getHasPrinted() {
            return printed;
        }
        
       // This method cancels the wizard, and returns the user to the  beginning of wizard  
        public PageReference cancel() {
            //PageReference contactPage = new ApexPages.StandardController(contact).view();
               if(isGuestUser){
           PageReference pageRef = new PageReference('/');
                       pageRef.setRedirect(true);
            return pageRef; 
                } 
                else{
            PageReference pageRef = new PageReference('/apex/StudentDataEntry');
                        pageRef.setRedirect(true);
            return pageRef; 
                }

        }
        
            
        // This method performs the final save for all objects, and
        // then navigates the user to the detail page for the new
        // medical form.
        // trying upsert instead of insert to avoid error when validation rule stalls process
        public PageReference save() {
            //Set mailing country to USA for all
            contact.MailingCountry = 'USA';          
            
          //try statement catches exceptions and passes them to apex:messages
            try{   
                saveHousehold();
                saveStudent();                            
                saveGuardian(contact2);          
                saveStudentGuardianRelationship(contact2, connector);
                if(secondGuardian) {
                    saveGuardian(guardian2);          
                    saveStudentGuardianRelationship(guardian2, studentGuardianConnector2);                                  
                }                
                saveEnrollment();
                saveMedForm();
                savePdf();
            } catch(Exception ex){
                ApexPages.addMessages(ex);
                return null;
            }               
            
            if( UserInfo.getUserType() == 'Guest' ) {            
                    PageReference confirmationPage = Page.HouseholdRegistrationConfirmation;
                    confirmationPage.setRedirect(false); // make it  false to make sure we keep the viewstate (the controller variables)
                    return confirmationPage;
            } else {
                // go to med form
                    PageReference pageRef = new PageReference('/' + medForm.id);
                    pageRef.setRedirect(true);
                    return pageRef;                     
            }
            
        }
    
        private void saveHousehold() {
          // Create the HH. Before inserting, copy the contact's
          // info into HH fields.
            household.MailingStreet__c = contact.MailingStreet;
            household.MailingCity__c = contact.MailingCity;
            household.MailingState__c = contact.MailingState;
            household.MailingPostalCode__c = contact.MailingPostalCode;
            household.MailingCountry__c =  contact.MailingCountry;
            upsert household;
        }
        
        private void saveStudent() {
            // Create the student. Before inserting, use the id field
            // that's created once the HH is inserted to create
            // the relationship between the contact and the HH.

            
            contact.ONEN_Household__c = household.id;
            contact.accountId = getLocalIndividualAccount();
            contact.RecordTypeId = getLocalRecordTypeId();
            //public site doesn't have field, autofills student          
            if(isGuestUser){
                contact.Person_Type__c = 'student';
            }     
            //if student from The Hamlin School, check do not contact boxes
            Id schoolId = enrollment.School__c;   
            
           	//modified by SR         
            List<Account> school = [select name from account where account.Id = :schoolId];                        
            if(school.size() > 0) {   
                if(school[0].Name == 'The Hamlin School') {
                    contact.HasOptedOutOfEmail =true;            
                    contact.Do_Not_Mail__c =true;
                    contact.Do_Not_Solicit__c = true;            
                }
           }              
           upsert contact;
        }   
            
        
        
        private void saveGuardian(Contact guardian) {
            // Create a guardian. Before inserting, use the id field
            // that's created once the HH is inserted to create
            // the relationship between the contact and the HH.
            guardian.ONEN_Household__c = household.id;
            guardian.accountId = contact.accountId;
            guardian.person_type__c = 'parent';
            guardian.MailingStreet = contact.MailingStreet;
            guardian.MailingCity = contact.MailingCity;
            guardian.MailingState = contact.MailingState;
            guardian.MailingPostalCode = contact.MailingPostalCode;
            guardian.MailingCountry =  contact.MailingCountry;
            guardian.MailingCountry =  contact.MailingCountry;
            guardian.HomePhone =  contact.HomePhone;
            //if student from The Hamlin School, check do not contact boxes
            Id schoolId = enrollment.School__c;           
            //modified by SR 
            List<Account> school = [select name from account where account.Id = :schoolId];                        
            if(school.size() > 0) {   
                if(school[0].Name == 'The Hamlin School') {
                    guardian.HasOptedOutOfEmail =true;            
                    guardian.Do_Not_Mail__c =true;
                    guardian.Do_Not_Solicit__c = true;            
                }
           }     
            upsert guardian;
        }    
                        
        private void saveStudentGuardianRelationship(Contact guardian, Contact_Connector__c connector) {
            // Create connection between guardian and student. Before inserting, use the id field
            // that's created by each contact to create
            // the relationship between the contacts.          
            //test if made previously when validation rule caused error and don't upsert if it exists
            //to avoid error from trying to upsert non-upsertable id fields.
          
            if (connector.id == null) {
                connector.Contact__c = guardian.id;
                connector.Related_Contact__c = contact.id;                      
                upsert connector;
            }
                
        }
                
        private void saveEnrollment() {
          // Create the enrollment. Before inserting, create 
          // a relationship with the contact.
          
            if (enrollment.id == null) {
                enrollment.Enrollee_Name__c = contact.id;
                enrollment.Role__c = contact.Person_Type__c;                
                upsert enrollment;
            }                       
        }
                
        private void saveMedForm() {
                // Create the medical form, linking to contact and enrollment          
            if (medform.id == null) {          
                medform.Student_Name__c = contact.id;
                medform.Name = enrollment.Name;
                medform.Student_Enrollment__c = enrollment.id;
                if(isGuestUser){
                    //set field for staff review for public site
                    medform.Serious_Medical_Condition_Summary__c = 'needs to be reviewed';
                } 
                //this section neeed only if internal wizard does not include full medical form
                //else{
                //set checkboxes to null so medform can be inserted on internal wizard 
                //medform.Allergies__c = false;
                //medform.Asthma__c = false; 
                //medform.Dietary_Restrictions__c = false; 
               
                //}             
                insert medform;
            }                       
        }

        private void savePdf() {
            Attachment pdfAttachment = new Attachment();
            Blob bodyOfPdfAttachment;
            try {
                pdfAttachment.Body = getPdf().getContent();
            } catch (VisualforceException e) {
                pdfAttachment.Body = Blob.valueOf('Some Text');
            }
            pdfAttachment.Name = 'medical_form.pdf';
            pdfAttachment.IsPrivate = false;
            pdfAttachment.ParentId = enrollment.id;
            insert pdfAttachment;
        }

        
        public boolean isGuestUser {
            get {
                return (UserInfo.getUserType() == 'Guest');
            }
        }
        
        public List<SelectOption> schools {
            get {
                List<SelectOption> schools = new List<SelectOption>();
                schools.add(new SelectOption('--None--', '--None--'));
                for(Account school: [select id, name from Account 
                    where recordTypeId=:getLocalSchoolRecordTypeId() and contract_school__c = true order by name])
                    schools.add(new SelectOption(school.id, school.name));
                return schools;
            }
        }
        
        public String school {
            get { return enrollment.school__c;} set {enrollment.school__c=value.equals('--None--')? null : value; schoolName=null; }
        }
        private String schoolName;
        public String getSchoolName() {
            if ((schoolName==null)&&(enrollment.school__c!=null))
                schoolName = [select name from Account where id = :enrollment.school__c].name;
            return schoolName;
        }
        

        public List<SelectOption> guardianRelationships {
            get {
                List<SelectOption> relationships = new List<SelectOption>();
                Schema.DescribeFieldResult f = Contact_Connector__c.Relationship__c.getDescribe();
                for(Schema.PicklistEntry relationship: f.getPicklistValues())
                    if(isValidGuardianRelationship(relationship.getLabel()))
                        relationships.add(new SelectOption(relationship.getLabel(), relationship.getLabel()));
                return relationships;
            }
        }
        
        public static boolean isValidGuardianRelationship(String relationship) {
            relationship = relationship.toLowerCase();
            return (!relationship.contains('son') && !relationship.contains('daughter'));       
        }
        
        public String primaryGuardianRelationship {
            get { return getConnector().relationship__c;} set {getConnector().relationship__c=value;}
        }

        public String secondaryGuardianRelationship {
            get { return getStudentGuardianConnector2().relationship__c;} set {getStudentGuardianConnector2().relationship__c=value;}
        }
                
        public List<SelectOption> teachers {
            get {
                List<SelectOption> teachers = new List<SelectOption>();
                teachers.add(new SelectOption('--None--', '--None--'));
                for(Contact teacher: [select id, name from Contact 
                    where recordTypeId=:getLocalTeacherRecordTypeId()
                    and contact.account.contract_school__c = true
                    and contact.Person_Type__c = 'teacher'])
                    teachers.add(new SelectOption(teacher.id, teacher.name));
                return teachers;
            }
        }
        
        public String teacher {
            get { return enrollment.teacher__c;} set {enrollment.teacher__c=value.equals('--None--')? null : value;}

        }
        
        public List<SelectOption> grades {
            get {
                List<SelectOption> grades = new List<SelectOption>();
                grades.add(new SelectOption('', '--None--'));
                
                Schema.DescribeFieldResult f = Student_Enrollment__c.Grade__c.getDescribe();
                for(Schema.PicklistEntry grade: f.getPicklistValues())
                    if(isValidGrade(grade.getLabel()))
                        grades.add(new SelectOption(grade.getLabel(), grade.getLabel()));
                        
                return grades;
            }
        }
        
        private boolean isValidGrade(String grade) {
            grade = grade.toLowerCase();
            
            String language = ApexPages.currentPage().getParameters().get('lang'); 
           if (language==null) 
                return (grade.contains('th')); 
           else if (language.equals('es')) 
                return (grade.contains('to')||grade.contains('otro')); 
           else   
                return (grade.contains('th')); 
           // if we add more languages, keep nesting if statements to pull up the correct list
        }
        
        public String grade {
            get { return enrollment.grade__c;} set {enrollment.Grade__c=value.equals('--None--')? null : value;}
        }
        
                
        private void verifyPrintedRegistration() {
            if(!isGuestUser)
                return;
            if(!printed)
                throw new NotPrintedException('Please print the registration!');
        }           
        public class NotPrintedException extends Exception{}      
        
        
        private void verifiesEmails() {
           // if(!this.isGuestUser) return;
                if(!isValidEmail(contact.email))
                if(!isValidEmail(contact2.email))
                        if((guardian2==null)||(!isValidEmail(guardian2.email)))
                                throw new NoEmailFoundException('At least one email must be provided!');
        }   
        
        public class NoEmailFoundException extends Exception{}
        
        private boolean isValidEmail(String email) {
                return (email!=null && email.length()>0); 
        }
                             
        /* 
        *   Returns the record id for the Record Type we use for students.
        *   This way we don't need to hard code record type ids in the code!
        */
        private String getLocalRecordTypeId() {
            Schema.DescribeSObjectResult contactDescribeResult = Schema.SObjectType.Contact;
            return contactDescribeResult.getRecordTypeInfosByName().get('Student').getRecordTypeId();               
        }

        public static String getLocalSchoolRecordTypeId() {
            Schema.DescribeSObjectResult describeResult = Schema.SObjectType.Account;
            return describeResult.getRecordTypeInfosByName().get('School').getRecordTypeId();               
        }

        private String getLocalTeacherRecordTypeId() {
            Schema.DescribeSObjectResult describeResult = Schema.SObjectType.Contact;
            return describeResult.getRecordTypeInfosByName().get('Staff/Teacher').getRecordTypeId();               
        }
        
        /*
        *   Returns the account id we want to use the household contacts under
        *   This way we don't need to hard code account ids in the code!
        */
        private String getLocalIndividualAccount() {
            // TODO is there a way to ensure that this account name is unique?
            return [select id from Account where name = 'Individual'].id;
        }
        
        private void fillHouseholdFields() {
            // let's ensure that the household variable has been initialized (it would be un-initialized if we remove all references to it from the visualforce pages)
            getHousehold();
            contact2.firstName =DataQualityUtilities.capitalizeFirstLetter(contact2.firstName); 
            contact2.lastName = DataQualityUtilities.capitalizeFirstLetter(contact2.LastName);
            contact.lastName = DataQualityUtilities.capitalizeFirstLetter(contact.LastName);

        Set<String> names =new Set<String>{contact.LastName, contact2.LastName};
        
        if (secondGuardian) { 
         guardian2.LastName = DataQualityUtilities.capitalizeFirstLetter(guardian2.LastName);
        names.add(guardian2.LastName);
        }
        
        household.Name=  'The ';
        
        for (String i : names) {
        
            household.Name = household.Name+ ' ' + i;
        
        }
        household.Name = household.Name+ ' Family'; 
        
            //code for household name that just uses guardian names
           // if (secondGuardian) { 
            //    if (contact2.LastName==guardian2.LastName)
            //    { 
             //       household.Name =  'The ' + contact2.LastName + ' Family';
            //    } else{
            //        guardian2.LastName = DataQualityUtilities.capitalizeFirstLetter(guardian2.LastName); 
            //        household.Name =  'The ' + contact2.LastName + ' ' + guardian2.LastName + ' Family';
            //    }
           
          //  } else{
           //     household.Name =  'The ' + contact2.LastName + ' Family';
          //  }  
               
               
               
                           
            //create Salutation based on Guardians' first names             
            if (secondGuardian) { 
                guardian2.firstName = DataQualityUtilities.capitalizeFirstLetter(guardian2.firstName);
                household.Recognition_Name_Short__c =  contact2.firstName + ' and ' + guardian2.firstName;
            } else{
                household.Recognition_Name_Short__c =  contact2.firstName;
            }               
        }        
        

   
}